package cn.iocoder.yudao.module.call.framework.client.impl.okcc;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.call.api.client.dto.*;
import cn.iocoder.yudao.module.call.framework.client.impl.AbstractCallClient;
import cn.iocoder.yudao.module.call.framework.client.CallCenter;
import cn.iocoder.yudao.module.call.api.client.dto.task.CreateCallTaskDTO;
import cn.iocoder.yudao.module.call.framework.client.property.CallProperties;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.call.enums.ErrorCodeConstants.*;

@Slf4j
public class OkccClient extends AbstractCallClient implements CallCenter {

    final static String url = "";

    @Override
    protected void doInit() {

    }

    public OkccClient(CallProperties properties) {
        super(properties);
        Assert.notNull(properties.getAppId(), "AppId不能为空，对应okcc的customer");
        Assert.notNull(properties.getAppSecret(), "AppSecret不能为空，对应apiSecret");

    }

    @Override
    public CallRespDTO handleCall(CallReqDTO callReqDTO) {
        return CallRespDTO.ofOk();
    }

    private Map<String, Object> buildAuthentication() {
        Long timestamp = System.currentTimeMillis();
        String sequence = RandomUtil.randomNumbers(5);
        return new HashMap<String, Object>() {{
            put("customer", properties.getAppId());
            put("timestamp", timestamp);
            put("seq", sequence);
            put("digest", makeAuthSign(sequence, timestamp));
        }};
    }

    private String makeAuthSign(String sequence, Long timestamp) {
        String md5Str = DigestUtil.md5Hex(StrUtil.concat(true, properties.getAppId(), "@", timestamp + "", "@", sequence, "@", properties.getAppSecret()));
        return md5Str.toLowerCase();
    }

    @Override
    public AgentRespDTO handleAgent(AgentReqDTO agentReqDTO) {
        String callMethod = agentReqDTO.getType();
        String requestUrl = StrUtil.concat(true, url, callMethod);
        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        body.put("request", new HashMap<String, Object>() {{
            put("agent", agentReqDTO.getAgent());
        }});
        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        String errMsg = "";
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject resp = jsonObject.getJSONObject("result");
            if (ObjUtil.equals(0, resp.get("error"))) {
                return AgentRespDTO.ok(agentReqDTO.getType(), agentReqDTO.getAgent());
            }
            errMsg = resp.getStr("msg");
        }
        return AgentRespDTO.error(agentReqDTO.getType(), agentReqDTO.getAgent(), errMsg);
    }

    @Override
    public CallNotifyDTO handleNotify(JSONObject jsonObject) {
        try {
            JSONObject notifyInfo = jsonObject.getJSONObject("notify");
            if (ObjectUtil.equal(notifyInfo.getStr("type"), "billing")) {
                return handleBilling(notifyInfo);
            }
            if (ObjectUtil.equal(notifyInfo.getStr("type"), "taskinfo")) {
                return handleTaskInfo(notifyInfo);
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private CallNotifyDTO handleTaskInfo(JSONObject notifyInfo) {
        CallNotifyDTO dto = new CallNotifyDTO();
        dto.setType("task");
        dto.setStatus(notifyInfo.getInt("status"));
        dto.setCalleeAmount(notifyInfo.getInt("calleeAmount"));
        dto.setRemainAmount(notifyInfo.getInt("remainAmount"));
        dto.setBatchTaskId(notifyInfo.getStr("taskID"));
        return dto;
    }

    public CallNotifyDTO handleBilling(JSONObject jsonObject) {
        boolean isBatchTask = StrUtil.isNotEmpty(jsonObject.getStr("taskID")) && Objects.equals(jsonObject.getStr("service"), "4");

        CallNotifyDTO callNotifyDTO = CallNotifyDTO.of(
                isBatchTask,
                jsonObject.getStr("taskID"),
                jsonObject.getStr("session"),
                jsonObject.getStr("typeResult"),
                jsonObject.getInt("callResult"),
                jsonObject.getStr("recordFile"),
                jsonObject.getInt("timeLength"),
                jsonObject.getStr("startTime"),
                jsonObject.getStr("answerTime"),
                jsonObject.getStr("byeTime"),
                jsonObject.getStr("staffNo"),
                jsonObject.getStr("callee")
        );
        callNotifyDTO.setUserData(jsonObject.getStr("userData"));
        return callNotifyDTO;
    }

    @Override
    public String callTaskControl(String taskId, String action) {
        String requestUrl = StrUtil.concat(true, url, "callTaskControl");

        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        body.put("request", new HashMap<String, Object>() {{
            put("taskID", taskId);
            put("action", action);
        }});

        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject result = jsonObject.getJSONObject("result");
            if (result.get("error").equals(0)) {
                JSONObject resp = jsonObject.getJSONObject("data").getJSONObject("response");
                return resp.getJSONObject("data").getStr("taskID");
            }
            throw exception(new ErrorCode(100500, result.getStr("msg")));
        }
        throw exception(HANDLE_TASK_ERROR);
    }




    @Override
    public boolean createAgent(AgentReqDTO agentReqDTO) {
        String requestUrl = StrUtil.concat(true, url, "createAgent");

        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        Map<String, Object> request = new HashMap<String, Object>() {{
            put("agent", agentReqDTO.getAgent());
            put("extension", agentReqDTO.getAgent());
            put("number", "1");
            put("agentPassword", agentReqDTO.getPassword());
            put("extensionPassword", agentReqDTO.getPassword());
            put("voiceRecord", "1");
        }};
        // 补充创建坐席时，添加班组信息
        if (StrUtil.isNotEmpty(agentReqDTO.getGroup1())) {
            request.put("group1", agentReqDTO.getGroup1());
        }
        if (StrUtil.isNotEmpty(agentReqDTO.getGroup2())) {
            request.put("group2", agentReqDTO.getGroup2());
        }
        body.put("request", request);
        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        log.info("createAgent request: {}", body);
        log.info("createAgent response: {}", httpResponse.body());
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject resp = jsonObject.getJSONObject("result");
            return ObjUtil.equals(0, resp.get("error"));
        }
        throw exception(CREATE_SIP_AGENT_ERROR);
    }

    @Override
    public void updateAgent(AgentReqDTO agentReqDTO) {
        String requestUrl = StrUtil.concat(true, url, "modifyAgentInformation");
        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        Map<String, Object> request = new HashMap<String, Object>() {{
            put("agent", ListUtil.of(agentReqDTO.getAgent()));
        }};
        if (StrUtil.isNotEmpty(agentReqDTO.getGroup1())) {
            request.put("group1", agentReqDTO.getGroup1());
        }
        if (StrUtil.isNotEmpty(agentReqDTO.getGroup2())) {
            request.put("group2", agentReqDTO.getGroup2());
        }
        body.put("request", request);
        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject resp = jsonObject.getJSONObject("result");
            ObjUtil.equals(0, resp.get("error"));
            return;
        }
        throw exception(UPDATE_SIP_AGENT_ERROR);
    }

    @Override
    public JSONObject getAccountInfo(String agent) {
        String requestUrl = StrUtil.concat(true, url, "getSIPAccount");

        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        body.put("request", new HashMap<String, Object>() {{
            put("agent", agent);
        }});

        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject result = jsonObject.getJSONObject("result");
            if (result.get("error").equals(0)) {
                JSONObject resp = jsonObject.getJSONObject("data").getJSONObject("response");
                return resp.getJSONObject("data");
            }
            throw exception(new ErrorCode(100500, result.getStr("msg")));
        }
        throw exception(GET_SIP_ACCOUNT_ERROR);
    }


    @Override
    public String addAgentGroup(AgentGroupReqDTO agentGroupReqDTO) {
        String requestUrl = StrUtil.concat(true, url, "addAgentGroup");
        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        body.put("request", new HashMap<String, Object>() {{
            put("name", agentGroupReqDTO.getGroupName());
            put("callDistribution", agentGroupReqDTO.getCallDistribution());
        }});
        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject result = jsonObject.getJSONObject("result");
            if (result.get("error").equals(0)) {
                JSONObject resp = jsonObject.getJSONObject("data").getJSONObject("response");
                return resp.getJSONObject("data").getStr("id");
            }
            throw exception(new ErrorCode(100500, result.getStr("msg")));
        }
        throw exception(CREATE_AGENT_GROUP_ERROR);
    }

    @Override
    public void updateAgentGroup(AgentGroupReqDTO agentGroupReqDTO) {

    }

    @Override
    public String createBatchCallTask(CreateCallTaskDTO createCallTaskDTO) {
        String[] method = new String[]{"", "callTaskCreateByGroup", "callTaskCreateByVoiceKeyScene", "callTaskCreateByVoiceAfterAgent", "callTaskCreateByVoiceTransferAgent"};
        String requestUrl = StrUtil.concat(true, url, method[createCallTaskDTO.getType()]);
        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        Map<String, Object> request = new HashMap<String, Object>() {{
            put("taskName", createCallTaskDTO.getName());
            put("mode", 2);
            put("agentGroup", createCallTaskDTO.getThirdPartyGroupId());
            put("multiplier", createCallTaskDTO.getMultiplier());
            put("concurrenceMode", createCallTaskDTO.getConcurrenceMode());
            put("callees", createCallTaskDTO.getCalleeList());
        }};
        if (Objects.nonNull(createCallTaskDTO.getCidGroup())) {
            request.put("CIDGroup", createCallTaskDTO.getCidGroup());
        }

        if (CollUtil.isNotEmpty(createCallTaskDTO.getWeekday1())) {
            request.put("weekday1", createCallTaskDTO.getWeekday1());
            request.put("startTime1", createCallTaskDTO.getStartTime1());
            request.put("endTime1", createCallTaskDTO.getEndTime1());
        }
        if (CollUtil.isNotEmpty(createCallTaskDTO.getWeekday2())) {
            request.put("weekday2", createCallTaskDTO.getWeekday2());
            request.put("startTime2", createCallTaskDTO.getStartTime2());
            request.put("endTime2", createCallTaskDTO.getEndTime2());
        }
        if (CollUtil.isNotEmpty(createCallTaskDTO.getWeekday3())) {
            request.put("weekday3", createCallTaskDTO.getWeekday3());
            request.put("startTime3", createCallTaskDTO.getStartTime3());
            request.put("endTime3", createCallTaskDTO.getEndTime3());
        }
        if (Objects.equals(1, createCallTaskDTO.getAutoRecall()) && Objects.equals(1, createCallTaskDTO.getType())) {
            request.put("autoRecall", createCallTaskDTO.getAutoRecall());
            request.put("recallTime", createCallTaskDTO.getRecallTime());
            request.put("recallResult", createCallTaskDTO.getRecallResult());
        }
        if (createCallTaskDTO.getType() == 2) {
            request.put("voiceFileID", createCallTaskDTO.getAudioFile());
            request.put("key1", createCallTaskDTO.getKey1());
            request.put("action1", createCallTaskDTO.getAction1());
            if (Objects.nonNull(createCallTaskDTO.getKey2()) && StrUtil.isNotEmpty(createCallTaskDTO.getKey2())&& StrUtil.isNotEmpty(createCallTaskDTO.getAction2())) {
                request.put("key2", createCallTaskDTO.getKey2());
                request.put("action2", createCallTaskDTO.getAction2());
            }
            if (Objects.nonNull(createCallTaskDTO.getKey3()) && StrUtil.isNotEmpty(createCallTaskDTO.getKey3()) && StrUtil.isNotEmpty(createCallTaskDTO.getAction3())) {
                request.put("key3", createCallTaskDTO.getKey3());
                request.put("action3", createCallTaskDTO.getAction3());
            }
        }
        if (createCallTaskDTO.getType() == 3) {
            request.put("voiceFileID", createCallTaskDTO.getAudioFile());
        }
        body.put("request", request);
        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject result = jsonObject.getJSONObject("result");
            log.info("createBatchCallTask request: {}", body);
            log.info("createBatchCallTask response: {}", httpResponse.body());

            if (result.get("error").equals(0)) {
                JSONObject resp = jsonObject.getJSONObject("data").getJSONObject("response");
                ResponseDTO res1 = BeanUtils.toBean(resp, ResponseDTO.class);
                if (createCallTaskDTO.getType() == 1) {
                    return res1.getData().getStr("taskID");
                }
                return resp.getStr("taskID");
            }
            throw exception(new ErrorCode(100500, result.getStr("msg")));
        }
        throw exception(CREATE_TASK_ERROR);
    }

    @Override
    public void updateBatchTask(CreateCallTaskDTO updateDTO) {
        String requestUrl = StrUtil.concat(true, url, "modifyCallTaskInformation");
        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        Map<String, Object> request = new HashMap<String, Object>() {{
            put("name", updateDTO.getName());
            put("taskID", updateDTO.getTaskId());
            put("multiplier", updateDTO.getMultiplier());
            put("concurrenceMode", updateDTO.getConcurrenceMode());
        }};
        body.put("request", request);
        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject result = jsonObject.getJSONObject("result");
            if (result.get("error").equals(0)) {
                JSONObject resp = jsonObject.getJSONObject("data").getJSONObject("response");
//                ResponseDTO res1 = BeanUtils.toBean(resp, ResponseDTO.class);
//                return resp.getJSONObject("data").getStr("taskID");
                return;
            }
            throw exception(new ErrorCode(100500, result.getStr("msg")));
        }
        throw exception(new ErrorCode(100500, "任务更新失败"));
    }

    @Override
    public Integer appendTaskNumber(String taskId, List<String> calleeList) {
        String requestUrl = StrUtil.concat(true, url, "callTaskAddNumbers");
        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());

        Map<String, Object> request = new HashMap<String, Object>() {{
            put("taskID", taskId);
            put("callees", calleeList);
        }};
        body.put("request", request);
        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject result = jsonObject.getJSONObject("result");
            if (result.get("error").equals(0)) {
                JSONObject resp = jsonObject.getJSONObject("data").getJSONObject("response");
                log.info("callTaskAddNumbers_resp: {}",resp);
                return resp.getJSONObject("result").getInt("succ");
            }
            throw exception(new ErrorCode(100500, result.getStr("msg")));
        }
        throw exception(APPEND_TASK_NUMBER_ERROR);
    }

    public VoiceFileRespDTO voiceFileUpload(VoiceFileUploadDTO voiceFileUploadDTO) {
        String requestUrl = StrUtil.concat(true, url, "VoiceFileUpload");
        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        body.put("request", new HashMap<String, Object>() {{
            put("fileName", voiceFileUploadDTO.getFileName());
            put("fileCode", voiceFileUploadDTO.getFileCode());
            put("userData", voiceFileUploadDTO.getUserData());
        }});

        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            log.info("voiceFileUpload response: {}", httpResponse.body());
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject result = jsonObject.getJSONObject("result");
            if (result.get("error").equals(0)) {
                JSONObject resp = jsonObject.getJSONObject("data").getJSONObject("response");
                return BeanUtils.toBean(resp, VoiceFileRespDTO.class);
            }
            throw exception(new ErrorCode(100500, result.getStr("msg")));
        }
        throw exception(CREATE_AGENT_GROUP_ERROR);
    }

    public List<CIDGroupListDTO> getCIDGroupList() {
        String requestUrl = StrUtil.concat(true, url, "getCIDGroupList");
        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        body.put("request", MapUtil.empty());
        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject result = jsonObject.getJSONObject("result");
            if (result.get("error").equals(0)) {
                JSONArray dataArray = jsonObject.getJSONObject("data").getJSONObject("response").getJSONArray("data");
                return BeanUtils.toBean(dataArray, CIDGroupListDTO.class);
            }
            throw exception(new ErrorCode(100500, result.getStr("msg")));
        }
        throw exception(new ErrorCode(100500, "获取CID分组失败"));
    }

    public ResponseDTO queryTaskInfo(String taskId) {
        String requestUrl = StrUtil.concat(true, url, "getTaskStatus");
        Map<String, Object> body = new HashMap<String, Object>();
        body.put("authentication", buildAuthentication());
        body.put("request", MapUtil.of("taskID", taskId));
        HttpRequest httpRequest = HttpUtil.createPost(requestUrl).body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject result = jsonObject.getJSONObject("result");
            if (result.get("error").equals(0)) {
                JSONObject resp = jsonObject.getJSONObject("data").getJSONObject("response");
                return BeanUtils.toBean(resp, ResponseDTO.class);
            }
            throw exception(new ErrorCode(100500, result.getStr("msg")));
        }
        throw exception(new ErrorCode(100500, "查询任务信息失败"));
    }

}
